import json

from django.shortcuts import render, redirect
from asgiref.sync import sync_to_async
from django.views.decorators.csrf import csrf_exempt
from exceptiongroup import catch


# Create your views here.
# 界面
from django.shortcuts import render
from asgiref.sync import sync_to_async

async def forward(request):
    conclusion = ''
    rules = [
        {'id': 1, 'name': '规则 1', 'description': '这是规则 1 的描述'},
        {'id': 2, 'name': '规则 2', 'description': '这是规则 2 的描述'},
        {'id': 3, 'name': '规则 3', 'description': '这是规则 3 的描述'},
        {'id': 4, 'name': '规则 4', 'description': '这是规则 4 的描述'},
        {'id': 5, 'name': '规则 5', 'description': '这是规则 5 的描述'},
    ]

    if request.method == 'POST':
        rule_ids = request.POST.getlist('rules')
        selected_rules = [rule for rule in rules if str(rule['id']) in rule_ids]

        if selected_rules:
            conclusions = [f"结论基于规则: {rule['description']}" for rule in selected_rules]
            conclusion = "\n".join(conclusions)

    return await sync_to_async(render)(request, 'infer_forward.html', {'rules': rules, 'conclusion': conclusion})

async def reverse(request):
    return await sync_to_async(render)(request, 'infer_reverse.html')

async def rules(request):
    return await sync_to_async(render)(request, 'infer_rules.html')

# 接口
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from inference_sys import  models

def launch_json(request):
    data = request.body.decode('utf-8')
    return json.loads(data)

@csrf_exempt
def get_rules(request):
    rules = models.Rule.objects.all().values('id', 'rule_name')
    rules_list = [{'id': rule['id'], 'name': rule['rule_name']} for rule in rules]
    return JsonResponse({'rules': rules_list})

@csrf_exempt
def add_rule(request):
    data = launch_json(request)
    models.Rule.objects.create(rule_name=data['rule_name'])
    return JsonResponse({'code': 100200, 'msg': '添加成功'})


@csrf_exempt
def delete_rule(request):
    data = launch_json(request)
    rule_name = data['rule_name']
    force_delete = data.get('force', False)  # 检查是否是强制删除

    if not force_delete:
        # 查找引用该规则的事实
        facts = models.Fact.objects.filter(pre_conditions__contains=rule_name)
        if facts.exists():
            # 如果有引用，返回相关事实
            conclusions = [fact.conclusion for fact in facts]
            return JsonResponse({
                'code': 100201,
                'msg': f'规则 "{rule_name}" 被以下事实引用: {", ".join(conclusions)}。是否确认删除？',
                'conclusions': conclusions
            })

    # 如果没有引用或用户确认删除，直接删除
    models.Rule.objects.filter(rule_name=rule_name).delete()
    return JsonResponse({'code': 100200, 'msg': '删除成功'})

@csrf_exempt
def edit_rule(request):
    data = launch_json(request)
    models.Rule.objects.filter(id=data['id']).update(rule_name=data['new_name'])
    return JsonResponse({'code': 100200, 'msg': '更新成功'})

@csrf_exempt
def get_facts_conclusions(request):
    if request.method == 'GET':
        conclusions = list(models.Fact.objects.values_list('conclusion', flat=True))
        return JsonResponse({'code': 100200, 'conclusions': conclusions})
    return JsonResponse({'code': 100405, 'msg': '不支持的请求方法'})
@csrf_exempt
def get_facts(request):
    facts = models.Fact.objects.all().values('id', 'pre_conditions', 'conclusion')
    facts_list = [{'id': fact['id'], 'pre_conditions': fact['pre_conditions'], 'conclusion': fact['conclusion']} for fact in facts]
    return JsonResponse({'facts': facts_list})

@csrf_exempt
def add_fact(request):
    data = launch_json(request)
    pre_conditions = data['pre_conditions']
    conclusion = data['conclusion']
    conditions_num = len(pre_conditions.split(' '))
    models.Fact.objects.create(pre_conditions=pre_conditions, conclusion=conclusion, conditions_num=conditions_num)
    return JsonResponse({'code': 100200, 'msg': '添加成功'})

@csrf_exempt
def delete_fact(request):
    data = launch_json(request)
    models.Fact.objects.filter(id=data['conclusion_id']).delete()
    return JsonResponse({'code': 100200, 'msg': '删除成功'})

@csrf_exempt
def edit_fact(request):
    data = launch_json(request)
    pre_conditions = data['new_pre_conditions']
    conclusion = data['new_conclusion']
    conditions_num = len(pre_conditions.split(' '))
    models.Fact.objects.filter(id=data['id']).update(pre_conditions=pre_conditions, conclusion=conclusion, conditions_num=conditions_num)
    return JsonResponse({'code': 100200, 'msg': '更新成功'})

@csrf_exempt
def batch_add_facts(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            facts = data.get('facts', [])

            for fact in facts:
                pre_conditions = fact.get('pre_conditions')
                conclusion = fact.get('conclusion')

                # 检查是否已经存在相同的事实
                if not models.Fact.objects.filter(pre_conditions=pre_conditions, conclusion=conclusion).exists():
                    models.Fact.objects.create(pre_conditions=pre_conditions, conclusion=conclusion)

            return JsonResponse({'code': 100200, 'msg': '批量添加事实成功'})
        except Exception as e:
            return JsonResponse({'code': 100500, 'msg': f'批量添加事实失败: {str(e)}'})
# 推理方法
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from inference_sys import models
import json

@csrf_exempt
def forward_rules(request):
    data = json.loads(request.body.decode('utf-8'))
    initial_conditions = set(data['rules'])  # 初始选中的规则名称列表

    facts = models.Fact.objects.all()
    conclusions = set(initial_conditions)
    queue = list(initial_conditions)  # 使用队列进行广度优先搜索
    reasoning_steps = []  # 用于记录推理步骤

    while queue:
        current_condition = queue.pop(0)

        for fact in facts:
            pre_conditions_set = set(fact.pre_conditions.split(' '))

            # 检查当前结论集是否包含所有前提条件
            if pre_conditions_set.issubset(conclusions):
                if fact.conclusion not in conclusions:
                    conclusions.add(fact.conclusion)
                    queue.append(fact.conclusion)
                    # 记录推理步骤
                    reasoning_steps.append(f"IF {' '.join(pre_conditions_set)} "
                                           f"THEN {fact.conclusion}")
    if reasoning_steps:
        msg = "推理成功，得出结论:\n" + "\n".join(
            [f"{i+1}. {step}" for i, step in enumerate(reasoning_steps)]
        )
    else:
        msg = "推理失败，选中的规则无法得出任何结论。"
    return JsonResponse({'code': 100200, 'msg': msg})


@csrf_exempt
def reverse_fact(request):
    if request.method == 'POST':
        data = launch_json(request)
        goal = data.get('goal')
        if not goal:
            return JsonResponse({'code': 100400, 'msg': '目标结论不能为空'})

        # 反向推理逻辑
        reasoning_steps = []
        known_preconditions = set()
        if backward_chain(goal, reasoning_steps, known_preconditions):
            reasoning_steps.reverse()  # 将推理步骤反转以从最底层开始显示
            str_preconditions = ''
            for pre_conditions in known_preconditions:
                str_preconditions += pre_conditions + " "
            str_preconditions = "所以 " + goal + " 所需要的事实为： " + str_preconditions
            reasoning_steps.append(str_preconditions)
            return JsonResponse({'code': 100200, 'msg': '推理成功', 'steps': reasoning_steps})
        else:
            return JsonResponse({'code': 100404, 'msg': '无法推导出目标结论'})


def backward_chain(goal, reasoning_steps, known_preconditions=None):
    known_conclusion = set()

    applicable_facts = models.Fact.objects.filter(conclusion=goal)
    all_facts = models.Fact.objects.all()
    for fact in all_facts:
        known_conclusion.add(fact.conclusion)

    if not applicable_facts.exists():
        return False

    for fact in applicable_facts:
        all_conditions_met = True
        for pre_condition in fact.pre_conditions.split(' '):
            known_preconditions.add(pre_condition)
            if pre_condition in known_conclusion:
                known_preconditions.remove(pre_condition)
                if not backward_chain(pre_condition, reasoning_steps, known_preconditions):
                    all_conditions_met = False
                    break
        if all_conditions_met:
            reasoning_steps.append(f"IF {fact.pre_conditions} THEN {goal}")
            return True

    return False